package com.mego.weblink.utils;

import android.Manifest;
import android.content.Context;
import android.content.pm.PackageManager;
import android.location.Criteria;
import android.location.GpsSatellite;
import android.location.GpsStatus;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.location.LocationProvider;
import android.os.Bundle;
import android.os.PowerManager;
import androidx.core.app.ActivityCompat;
import android.widget.Toast;

import java.util.ArrayList;
import java.util.Iterator;


public class GPSProvider {

    private Context mContext;

    private LocationManager mlocManager = null;
    private Location mlastValidLoc = null;

    private LocationManager networkLocationManager;
    private Location mNetValidLoc = null;

    private static final int MINTIME = 2000;
    private static final int MININSTANCE = 2;

    private GpsStatus mGpsStatus = null;
    private Iterable<GpsSatellite> mAllSatellites = null;
    private boolean mFixed = false;

    private PowerManager pm;
    private PowerManager.WakeLock wakeLock;

    private static GPSProvider instance = new GPSProvider();

    public static GPSProvider getInstance() {
        return instance;
    }

    public GPSProvider() {
    }

    public void initGPSProvider(Context context) {
        mContext = context;

        pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
        //保持cpu一直运行，不管屏幕是否黑屏
        wakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "weblink:CPUKeepRunning");
        wakeLock.acquire();

        // GPS定位
        try {
            mlocManager = (LocationManager) mContext.getSystemService(Context.LOCATION_SERVICE);
            if (ActivityCompat.checkSelfPermission(context, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED
                    && ActivityCompat.checkSelfPermission(context, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
                // TODO: Consider calling
                //    ActivityCompat#requestPermissions
                // here to request the missing permissions, and then overriding
                //   public void onRequestPermissionsResult(int requestCode, String[] permissions,
                //                                          int[] grantResults)
                // to handle the case where the user grants the permission. See the documentation
                // for ActivityCompat#requestPermissions for more details.
                return;
            }
            mlocManager.requestLocationUpdates(LocationManager.GPS_PROVIDER,
                    1000, 0, mlocListener);
        } catch (Exception e) {
            return;
        }

        // 基站定位
        try {
            networkLocationManager = (LocationManager) mContext
                    .getSystemService(Context.LOCATION_SERVICE);
            networkLocationManager.requestLocationUpdates(
                    LocationManager.NETWORK_PROVIDER, MINTIME, MININSTANCE,
                    netlocationListener);
        } catch (Exception e) {
            return;
        }

        openGpsStatus();

        openGPS();
    }

    public void openGpsStatus() {
        if (ActivityCompat.checkSelfPermission(mContext, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
            return;
        }
        mlocManager.addGpsStatusListener(mStatusListener);
    }

    public void closeGpsStatus() {
        mlocManager.removeGpsStatusListener(mStatusListener);
    }

    public boolean isGPSEnabled() {
        if (mlocManager == null)
            return false;
        return mlocManager
                .isProviderEnabled(LocationManager.GPS_PROVIDER);
    }

    public void openGPS() {
        if (mlocManager == null)
            return;

        if (mlocManager.isProviderEnabled(LocationManager.GPS_PROVIDER)) {
            Toast.makeText(mContext, "GPS已经开启！", Toast.LENGTH_SHORT).show();
        } else {
            Toast.makeText(mContext, "GPS未开启！请开启GPS并重启应用。", Toast.LENGTH_SHORT).show();
        }

    }

    private String getProvider() {
        if (mlocManager == null)
            return null;

        Criteria criteria = new Criteria();
        criteria.setAccuracy(Criteria.ACCURACY_FINE);
        criteria.setAltitudeRequired(false);
        criteria.setBearingRequired(false);
        criteria.setCostAllowed(true);
        criteria.setPowerRequirement(Criteria.POWER_LOW);

        return mlocManager.getBestProvider(criteria, true);
    }

    private final LocationListener netlocationListener = new LocationListener() {

        public void onStatusChanged(String provider, int status, Bundle extras) {
        }

        public void onProviderEnabled(String provider) {
        }

        public void onProviderDisabled(String provider) {
        }

        public void onLocationChanged(Location location) {
            if (location != null) {
                mNetValidLoc = location;
            }
        }
    };

    private final LocationListener mlocListener = new LocationListener() {
        @Override
        public void onLocationChanged(Location location) {
            if (location != null) {
                mlastValidLoc = location;
            }
        }

        @Override
        public void onProviderDisabled(String provider) {
        }

        @Override
        public void onProviderEnabled(String provider) {
        }

        @Override
        public void onStatusChanged(String provider, int status, Bundle extras) {
            if (status == LocationProvider.AVAILABLE) {
                mFixed = true;
            } else if (status == LocationProvider.OUT_OF_SERVICE) {
                mFixed = false;
            } else if (status == LocationProvider.TEMPORARILY_UNAVAILABLE) {
                mFixed = false;
            }
        }
    };

    public Iterable<GpsSatellite> GetSatellite() {
        return mAllSatellites;
    }

    private final GpsStatus.Listener mStatusListener = new GpsStatus.Listener() {
        @Override
        public void onGpsStatusChanged(int event) {
            if (ActivityCompat.checkSelfPermission(mContext, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
                // TODO: Consider calling
                //    ActivityCompat#requestPermissions
                // here to request the missing permissions, and then overriding
                //   public void onRequestPermissionsResult(int requestCode, String[] permissions,
                //                                          int[] grantResults)
                // to handle the case where the user grants the permission. See the documentation
                // for ActivityCompat#requestPermissions for more details.
                return;
            }
            mGpsStatus = mlocManager.getGpsStatus(null);

            switch (event) {
                case GpsStatus.GPS_EVENT_FIRST_FIX:
                    mGpsStatus.getTimeToFirstFix();
                    break;
                case GpsStatus.GPS_EVENT_SATELLITE_STATUS:
                    mAllSatellites = mGpsStatus.getSatellites();
                    setSatelliteList();
                    break;
                case GpsStatus.GPS_EVENT_STARTED:
                    break;
                case GpsStatus.GPS_EVENT_STOPPED:
                    break;
                default:
                    break;
            }
        }
    };

    public float getSpeed() {
        if (mlastValidLoc == null || !mFixed)
            return (float) 0.0;

        return mlastValidLoc.getSpeed();
    }

    public float getDirection() {
        if (mlastValidLoc == null)
            return (float) 0.0;
        return mlastValidLoc.getBearing();
    }

    public float getAccuracy() {
        if (mlastValidLoc == null)
            return 100;
        return mlastValidLoc.getAccuracy();
    }

    public long getTime() {
        if (mlastValidLoc == null)
            return 0;
        return mlastValidLoc.getTime();
    }

    public LonLat getPos() {
        LonLat pos = new LonLat();
        if (mlastValidLoc != null) {
            pos = new LonLat(mlastValidLoc.getLongitude(),
                    mlastValidLoc.getLatitude());
        }

        if (!pos.IsValid() && mNetValidLoc != null) {
            pos = new LonLat(mNetValidLoc.getLongitude(),
                    mNetValidLoc.getLatitude());
        }
        return pos;
    }

    public double getAltitude() {
        if (mlastValidLoc == null)
            return 0;
        return mlastValidLoc.getAltitude();
    }

    public boolean isFixed() {
        return mFixed;
    }

    public int getGPSNum() {
        if (mGpsStatus == null || mAllSatellites == null)
            return 0;

        mSatelliteList.clear();
        int count = 0;
        try {
            for (Iterator<GpsSatellite> it = mAllSatellites.iterator(); it
                    .hasNext(); ) {
                GpsSatellite gpsState = it.next();
                mSatelliteList.add(gpsState);
                if (gpsState.usedInFix())
                    count++;
            }
        } catch (Exception e) {

        }
        return count;
    }

    private ArrayList<GpsSatellite> mSatelliteList = new ArrayList<GpsSatellite>();

    public ArrayList<GpsSatellite> getGpsSatellite() {
        return mSatelliteList;
    }

    private final int MAX_GPS_SATELLITE_NUM = 32;
    public int nPRN[] = new int[MAX_GPS_SATELLITE_NUM];
    ;
    public float nSNR[] = new float[MAX_GPS_SATELLITE_NUM];
    public float nElevation[] = new float[MAX_GPS_SATELLITE_NUM];
    public float nAzimuth[] = new float[MAX_GPS_SATELLITE_NUM];

    private void setSatelliteList() {
        if (mGpsStatus == null)
            return;

        mSatelliteList.clear();
        int count = 0;
        for (Iterator<GpsSatellite> it = mAllSatellites.iterator(); it
                .hasNext(); ) {
            GpsSatellite gpsState = it.next();
            mSatelliteList.add(gpsState);
            if (gpsState.usedInFix())
                count++;
        }

        if (count >= 4) {
            mFixed = true;
        } else {
            mFixed = false;
        }

        for (int i = 0; i < mSatelliteList.size() && i < MAX_GPS_SATELLITE_NUM; i++) {
            nAzimuth[i] = mSatelliteList.get(i).getAzimuth();
            nElevation[i] = mSatelliteList.get(i).getElevation();
            nSNR[i] = mSatelliteList.get(i).getSnr();
            nPRN[i] = mSatelliteList.get(i).getPrn();
        }
    }

}
